'''
Created on Dec 28, 2011

@author: Bing

'''

import json, types
from common import server_log, framework, utils
from common.server_exception import ServerError

# Added to print logs of different requests in one place to 
# avoid printing logs in each request handler by Bing on Dec 28, 2011
# Input argument:
# request_handler: the function for handling GET/POST/PUT etc requests
def process_request(request_handler):
    try:
        __log_request()
        result = request_handler()
        
    except ServerError,e:
        server_log.error(mail=True)
        return _response(e.status_code, e.error_message)
    except Exception,e:
        server_log.error()
        return _response()
    else:   # successful
        if result != '304':
            return _response("0", result)


# qizhao: wrap response body, and generate json string
def _response(status = "1", 
             data = "Server request execution failed."):
    try:
        if status == "1":
            resp_json = data
        else:
            resp_json = json.dumps(data, default=__to_json)
        resp = {'StatusCode': status,
                'ResponseData': resp_json}

        __log_response(status, resp_json)
        
        return json.dumps(resp, default=__to_json)
    except Exception:
        server_log.error()
        return None

def __to_json(python_object):
    """
    convert python object to a dictionary, since json.dump can't deal with python object directly
    """
    if isinstance(python_object, types.InstanceType):
        return python_object.__dict__
    raise TypeError(repr(python_object) + 'is not JSON serializable')

def __log_response(status, body):
    try:
        resp_prefix = '[RESPONSE TO %s]' % framework.get_remote_addr()
            
        server_log.info(('%s STATUS: %s, URL: %s %s' % (resp_prefix, 
                                                        status, 
                                                        framework.get_request_method(), 
                                                        framework.get_path_info()), 
                         '%s BODY: %s' % (resp_prefix, body)))
    except Exception:
        server_log.warning('Fail to print response info')

def __log_request():
    try:
        req_prefix = '[REQUEST FROM %s]' % framework.get_remote_addr()
        
        req_url = '%s %s %s' % (req_prefix,
                                framework.get_request_method(),
                                framework.get_path_info())
        
        query_string = framework.get_query_string()
        if query_string:
            req_url += "?%s" % query_string
        
        geo_location = framework.get_http_geo_location()
        if geo_location:
            user_loc = framework.get_http_geo_location()[1:-1]
        else:
            user_loc = 'UNKNOWN'
        
        timezone = framework.get_http_secondsfromgmt()
        
        user_id = utils.get_id_from_header()
        if user_id is None:
            user_id = 'UNKNOWN'
        
        req_other = '%s USER ID: %s, GEO: %s, TIMEZONE: %s' % (req_prefix, user_id, user_loc, timezone)   
        
        post_data = None
        # HiJack: TODO: [yali][01/11/2012]: don't record POST body in upload file controllers
        path = framework.get_path()
        if not (path.startswith("upload/file") or path.startswith("file/upload")):
            post_data = framework.get_post_body()

        if post_data:
            req_body = '%s BODY: %s' % (req_prefix, post_data)
            server_log.info((req_url, req_body, req_other))
        else:
            server_log.info((req_url, req_other))
    except Exception:
        server_log.warning('Fail to print request info')